package com.yuanxiao.common.core.utils;

import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
public class ListUtils {

    public static List<Object> getObjectIdList(List sourceList, String idProp){
        if(sourceList==null || sourceList.size ()==0) return new ArrayList<> ();
        return (List<Object>) sourceList.stream().map(sur ->{
            return getValueByPropName (sur, idProp);
        }).distinct().collect(Collectors.toList());
    }

    /**
     * lambda表达式对两个List进行循环,根据符合条件,进行相关的赋值操作并返回这个对象集合
     * @param sourceList   待设置源列表
     * @param srcEqualProp   源对象条件判断属性名
     * @param srcSetProp     源对象待设置属性名
     * @param targetList     资源提供者列表
     * @param tarEqualProp   对象条件判断参数名
     * @param tarGetProp     待获取对象属性名
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T,U>List<T> setListByEqualObjProperty(
            List<T> sourceList, String srcEqualProp, String srcSetProp,
            List<U> targetList, String tarEqualProp, String tarGetProp
    ){
        if(sourceList==null || sourceList.size ()==0 || targetList==null || targetList.size ()==0) return sourceList;
        List<T> resultList = sourceList.stream()
                .map(sur-> targetList.stream()
                        .filter(tar -> Objects.equals(getValueByPropName(sur, srcEqualProp), getValueByPropName(tar, tarEqualProp)))
                        .findFirst()
                        .map(tar -> {
                            setValueByPropName(sur, srcSetProp, getValueByPropName(tar, tarGetProp));
                            return sur;
                        } ).orElse(null))
                .collect(Collectors.toList());

        return  resultList;
    }

    /**
     * 通过遍历两个List中按id属性相等的归结到resultList中
     * @param oneList  源list 1
     * @param twoList  源list 2
     * @param equalKeyName 相等的map键值
     */
    public static List<Map<Object, Object>> compareListHitData(List<Map<Object, Object>> oneList, List<Map<Object, Object>> twoList, Object equalKeyName) {
        if(oneList==null || oneList.size ()==0 || twoList==null || twoList.size ()==0) return oneList;
        List<Map<Object, Object>> resultList = oneList.stream().map(map -> twoList.stream()
                .filter(m -> Objects.equals(m.get(equalKeyName),map.get(equalKeyName)))
                .findFirst().map(m -> {
                    map.putAll(m);
                    return map;
                }).orElse(null))
                .filter(Objects::nonNull).collect(Collectors.toList());
        return resultList;
    }


    /**
     * 通过属性获取传入对象的指定属性的值
     * @param object 对象
     * @param propName 属性名
     * @param <T>
     * @return
     */
    public static <T> T getValueByPropName(Object object, String propName) {
        T value = null;
        try {
            // 通过属性获取对象的属性
            Field field = object.getClass().getDeclaredField(propName);
            // 对象的属性的访问权限设置为可访问
            field.setAccessible(true);
            // 获取属性的对应的值
            value = (T)field.get(object);
        } catch (Exception e) {
            return null;
        }

        return value;
    }

    /**
     * 通过属性设置传入对象的指定属性的值
     * @param object 对象
     * @param propName 属性名
     * @param updateValue 属性值
     * @param <U>
     */
    public static <U> void setValueByPropName(Object object, String propName, U updateValue) {

        try {
            // 通过属性获取对象的属性
            Field field = object.getClass().getDeclaredField(propName);
            // 对象的属性的访问权限设置为可访问
            field.setAccessible(true);
            // 设置属性的对应的值
            field.set(object, updateValue);
        } catch (Exception e) {
            log.error("setValueByPropName.error {}", propName, e);
        }

    }


}
